package internal

import (
	"github.com/name5566/leaf/gate"
	"lol.com/feb214-game/nest.git/leaf"
	"lol.com/feb214-game/nest.git/log"
	"lol.com/feb214-game/nest.git/user"
	"reflect"
	"sync/atomic"
	"talent.com/cube/common/cxt"
	"talent.com/cube/common/msg"
	"talent.com/cube/conf/g"
	"time"
)

func handle(m interface{}, h func([]interface{})) {
	t := reflect.TypeOf(m)
	skeleton.RegisterChanRPC(t, func(args []interface{}) {
		log.Debug("receive user %v: %+v", t, args[0])
		h(args)
	})
}

func init() {
	skeleton.RegisterChanRPC("NewAgent", rpcNewAgent)
	skeleton.RegisterChanRPC("CloseAgent", rpcCloseAgent)
	skeleton.RegisterChanRPC(g.EventReleaseGoldLock, handleReleaseGoldLock)
	handle(&msg.AuthReq{}, handleAuth)
	handle(&msg.BetReq{}, handleBet)
	handle(&msg.BankerReq{}, handleBanker)
}

/*---------------------------------------
	框架内部消息回调
 ---------------------------------------*/
//新建agent的回调
//新建连接Ns之内不认证则直接关闭
func rpcNewAgent(args []interface{}) {
	ag := args[0].(gate.Agent)
	skeleton.AfterFunc(5*time.Second, func() {
		leaf.CheckAuth(ag)
	})
}

//关闭agent时的回调
func rpcCloseAgent(args []interface{}) {
	ag := args[0].(gate.Agent)
	if ag.UserData() != nil {
		uc, ok := ag.UserData().(*cxt.UserContext)
		if !ok {
			return
		}
		tc := cxt.GetTableContext(uc.TableID)
		logoutUser(uc, tc)
	}
}

//在同步下注信息结束后移除金币锁
func handleReleaseGoldLock(args []interface{}) {
	userID := args[0].(uint64)
	gameType := args[1].(int32)
	//获取最新的uc，用户有可能重新接入
	uc := cxt.GetUserContext(userID)
	if uc == nil || (atomic.LoadInt32(&uc.Disconnect) == 1 && uc.CostSyncCounter.Cleared()) {
		imCache := g.GetPublicCache(gameType)
		_ = imCache.RemoveUser(userID)
		log.Info("release user %v gold lock from %v after sync", userID, g.GetCodeLabel(gameType))
	}
}

func handleAuth(args []interface{}) {
	// 收到的消息
	req := args[0].(*msg.AuthReq)
	// 消息的发送者
	ag := args[1].(gate.Agent)
	var (
		allow bool
		info  *user.MixedInfo
	)
	skeleton.Go(func() {
		allow, info = authUser(req, ag)
	}, func() {
		if allow {
			loginUser(req, ag, info)
		}
	})
}

func transferEventToTable(args []interface{}, eventNo int) {
	ag := args[1].(gate.Agent)
	if !leaf.CheckAuth(ag) {
		return
	}
	uc, ok := ag.UserData().(*cxt.UserContext)
	if !ok || uc == nil {
		return
	}
	tc := cxt.GetTableContext(uc.TableID)
	if tc == nil {
		return
	}
	//转发到房间里面
	tc.RPC.Go(eventNo, uc, tc, args[0])
}

func handleBet(args []interface{}) {
	transferEventToTable(args, g.EventUserBet)
}

func handleBanker(args []interface{}) {
	transferEventToTable(args, g.EventUserBanker)
}
